import { ref, computed } from 'vue'
import { defineStore } from 'pinia'
import { nebulaExec } from '@/utils/request'
import { useSchemaStore } from './schema'

export const usePortraitStore = defineStore('userPortrait', () => {
  const EDGE_TYPES = ['abnorm_trans_card', 'card_weimao_label', 'gambling_card']
  const isLoading = ref(true)
  const mobile = ref(null)
  const schemaStore = useSchemaStore()
  const schemas = schemaStore.schemas

  const vid = ref(null)
  const card = ref(null)
  const month = ref(null)
  const months = ref([])
  const basicInfo = ref(null)
  const cards = ref(null)

  const rawData = ref(null)
  const edges = ref([])

  // TODO: mobile sm3 encode
  async function getBasicInfo() {
    try {
      // Use mobile as top query id
      const resp = await nebulaExec(
        `MATCH (m)-[e:mobile_belongsto]->(v)-[e1:has_card]->(c) where id(m) == "${mobile.value}" return v,id(c)`,
      )
      vid.value = resp.v[0].vid
      basicInfo.value = resp.v[0].tags.person_infom
      cards.value = Object.fromEntries(
        resp['id(c)'].map((e: unknown) => [
          e,
          Object.fromEntries(EDGE_TYPES.map((e1) => [e1, {}])),
        ]),
      )
    } catch (error) {
      throw error
    }
  }

  async function getScenarioData() {
    try {
      const promises = Object.keys(cards.value).map((c) =>
        nebulaExec(`MATCH (v)-[e]->(v) where id(v) == "${c}" RETURN e`),
      )
      const resps = await Promise.all(promises)
      console.log(resps)
      resps.forEach((resp) => {
        resp.e
          .filter((edge) => EDGE_TYPES.includes(edge.type))
          .forEach((edge) => {
            if (!months.value.includes(edge.rank)) {
              months.value.push(edge.rank)
            }
            cards.value[edge.src][edge.type][edge.rank] = edge.props
          })
      })

      // const promises = EDGE_TYPES.map((t: string) =>
      //   nebulaExec(`MATCH PROP ON ${t} "${card}" -> "${card}"@${month} YIELD properties(edge)`),
      // )
      // const resps = await Promise.all(promises)
      // const resp = await nebulaExec(
      //   `FETCH PROP ON ${scenario} "${card}" -> "${card}"@${month} YIELD properties(edge)`,
      // )

      // const promises = tags.Name.map((t: string) => nebulaExec(`desc tag ${t}`))
      // scenarios.value[scenario] ??= {}
      // scenarios.value[scenario][id] ??= {}
      // scenarios.value[scenario][id][month] ??= resp['properties(EDGE)'][0]
      // return scenarios.value[scenario][id][month]
    } catch (error) {
      throw error
    }
  }

  async function getEdges() {
    try {
      const resp = await nebulaExec(
        `MATCH (m)-[]->(u)-[]->(v)-[e]->(v) WHERE id(m) == "${mobile.value}" RETURN e`,
      )
      edges.value = resp.e
    } catch (err) {
      throw err
    }
  }

  const cardPortrait = (scenario: string) => {
    return edges.value
      .filter((e) => e.src == card.value && e.rank == month.value)
      .find((e) => e.type == scenario)
  }

  async function getData() {
    try {
      isLoading.value = true
      await schemaStore.load()
      await getBasicInfo()
      await getScenarioData()
      await getEdges()
      card.value = Object.keys(cards.value)[0]
      month.value = months.value[0]
    } catch (error) {
      console.error('Error fetching data:', error)
      throw error
    } finally {
      isLoading.value = false
    }
  }

  function setCard(cardNo: string) {
    card.value = cardNo
  }

  function setMonth(m: string) {
    month.value = m
  }

  // const basicInfo = computed(() => {
  //   const data = Object.entries(rawData.value.u[0].tags.person_infom).map(([k, v]) => [
  //     k,
  //     { name: schemas.value['person_infom'][k] || k, val: v },
  //   ])
  //   return Object.fromEntries(data)
  // })

  // const cardById = computed((cardNo: string) => {
  //   return rawData.value.cards
  // })

  // const cards = computed(() => {
  //   if (!rawData.value) {
  //     return {}
  //   }
  //   const c = {}
  //   rawData.value.c.forEach((current: unknown) => {
  //     c[current.vid] = current.tags.card
  //     c[current.vid].scenarios = {}
  //   })
  //   rawData.value.e1.forEach((e: unknown) => {
  //     c[e.src].scenarios[e.type] = c[e.src].scenarios[e.type] || {}
  //     const p = Object.fromEntries(
  //       Object.keys(e.props).map((k) => [
  //         k,
  //         { name: schemas.value[e.type][k] || k, val: e.props[k] },
  //       ]),
  //     )
  //     c[e.src].scenarios[e.type][e.rank] = p
  //   })
  //   return c
  // })

  async function fetchData(id: string) {
    try {
      isLoading.value = true

      rawData.value = await nebulaExec(
        'match (u)-[e:has_card]->(c)-[e1]->(c) where id(u) == "' + id + '" return u,c,e1',
      )
    } catch (error) {
      console.error('Error fetching user data:', error)
    } finally {
      isLoading.value = false
    }
  }
  // initSchemas()

  return {
    isLoading,
    cards,
    rawData,
    mobile,
    months,
    edges,
    card,
    month,
    fetchData,
    basicInfo,
    schemas,
    getScenarioData,
    getData,
    cardPortrait,
    setCard,
    setMonth,
  }
})
